//------------------------------------------------------------------------------------------------
// The MIT License (MIT)
// 
// Copyright (c) 2019 Crsky
// 
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
// 
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//------------------------------------------------------------------------------------------------

#include "base_types.h"
#include "engine.h"
#include "high_resolution_timer.h"
#include "host.h"


//------------------------------------------------------------------------------------------------
// Implementation
//------------------------------------------------------------------------------------------------
class CEngine : public IEngine
{
public:
	CEngine();
	CEngine( const CEngine& ) = delete;
	CEngine& operator=( const CEngine& ) = delete;
	~CEngine();

public:
	virtual bool Load( bool dedicated ) override;
	virtual void UnLoad() override;
	virtual void Frame() override;
	virtual QuitAction GetQuitAction() override;
	virtual void SetQuitAction( QuitAction action ) override;

private:
	// Set an action to quit the engine...
	QuitAction quit_action_;

	// The engine timer
	HighResolutionTimer timer_;

	// The engine frame timers
	double current_time_;
	double previous_time_;
	double frame_time_;
};

//------------------------------------------------------------------------------------------------
// Constructor
//------------------------------------------------------------------------------------------------
CEngine::CEngine()
	: quit_action_( QuitAction::Nothing )
	, timer_()
	, current_time_( 0 )
	, previous_time_( 0 )
	, frame_time_( 0 )
{
}

//------------------------------------------------------------------------------------------------
// Destructor
//------------------------------------------------------------------------------------------------
CEngine::~CEngine()
{
}

//------------------------------------------------------------------------------------------------
// Purpose: 
//------------------------------------------------------------------------------------------------
bool CEngine::Load( bool dedicated )
{
	timer_.Start();

	if ( !dedicated )
	{
		// Initialize graphics, sound etc.
	}

	return true;
}

//------------------------------------------------------------------------------------------------
// Purpose: 
//------------------------------------------------------------------------------------------------
void CEngine::UnLoad()
{
	timer_.Stop();
}

//------------------------------------------------------------------------------------------------
// Run engine frame
//------------------------------------------------------------------------------------------------
void CEngine::Frame()
{
	// Update current time
	current_time_ = timer_.GetElapsedTimeInSec();

	// Calcuate frame interval
	frame_time_ = current_time_ - previous_time_;
	previous_time_ = current_time_;

	// Run host
	Host()->Frame( frame_time_ );
}

//------------------------------------------------------------------------------------------------
// Getter
//------------------------------------------------------------------------------------------------
CEngine::QuitAction CEngine::GetQuitAction()
{
	return quit_action_;
}

//------------------------------------------------------------------------------------------------
// Setter
//------------------------------------------------------------------------------------------------
void CEngine::SetQuitAction( QuitAction action )
{
	quit_action_ = action;
}

//------------------------------------------------------------------------------------------------
// Returns the singleton of the engine
//------------------------------------------------------------------------------------------------
IEngine * Engine()
{
	static CEngine engine;
	return &engine;
}
